# 属性绑定

将 data 中数据插入到 HTML 模版属性中

# : v-bind

  • 预期any (with argument) | Object (without argument)

  • 参数attrOrProp (optional)。大致理解 attr 为 HTML 属性(可自定义),prop 为 JS 属性

  • 修饰符

    • .prop - 作为一个 DOM property 绑定而不是作为 attribute 绑定。(差别在哪里?)
    • .camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase. (从 2.1.0 开始支持)。见Style绑定
    • .sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。
  • 用法动态地绑定一个或多个特性,或向另一个组件传递 props 值

    • 在绑定 classstyle 特性时,支持其它类型的值,如数组或对象。可以通过下面的教程链接查看详情。

    • 在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。

    • 没有参数时,可以绑定到一个包含键值对的对象。注意此时 classstyle 绑定不支持数组和对象。

  • 示例

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Title</title>
      </head>
    
      <body>
        <div id="app">
          <a :href="href">QQ</a>
        </div>
    
        <script src="/lib/vue.js"></script>
        <script>
          const vm = new Vue({
            el: "#app",
            data: {
              message: "Hello",
              href: "https://www.qq.com",
            },
          });
        </script>
      </body>
    </html>
    
    <!-- 绑定一个属性 -->
    <img v-bind:src="imageSrc">
    <!-- 缩写 -->
    <img :src="imageSrc">
    
    <!-- 动态特性名 (2.6.0+) -->
    <button v-bind:[key]="value"></button>
    <!-- 动态特性名缩写 (2.6.0+) -->
    <button :[key]="value"></button>
    
    <!-- 绑定一个有属性的对象 -->
    <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
    
    <!-- 通过 prop 修饰符绑定 DOM 属性 -->
    <div v-bind:text-content.prop="text"></div>
    
    <!-- prop 绑定。“prop”必须在 my-component 中声明。-->
    <my-component :prop="someThing"></my-component>
    
    <!-- 通过 $props 将父组件的 props 一起传给子组件 -->
    <child-component v-bind="$props"></child-component>
    
    <!-- XLink -->
    <svg><a :xlink:special="foo"></a></svg>
    

    .camel 修饰符允许在使用 DOM 模板时将 v-bind 属性名称驼峰化,例如 SVG 的 viewBox 属性:

    <svg :view-box.camel="viewBox"></svg>
    

    在使用字符串模板或通过 vue-loader/vueify 编译时,无需使用 .camel

# 绑定 HTML class 🔥

# 绑定对象(使用很多)

  • 根据truthy(真值,除 false0""nullundefinedNaN 以外)来决定键的渲染

    :class="{class1: boolean, class2: boolean}"
    
  • 会和普通的 class 共存

    <span class="class1" :class="class2"></span>
    
  • 若过于复杂,可放入 methods 或 compute 中。method必须加括号来调用该方法(与@调用不一样!);compute 属性不用加括号方法中只要返回对象或数组

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <style>
      .active {
        color: red;
      }

      .underline {
        text-decoration: underline;
      }
    </style>
  </head>

  <body>
    <div id="app">
      class对象写死:
      <span :class="{active: true, underline: false}">{{message}}</span><br />
      class对象绑定:
      <span :class="{active: isActive, underline: isUnderline}"
        >{{message}}</span
      >
      <button @click="changeActive">切换 active</button><br />
      class对象方法绑定:
      <span :class="myClassMthod()">{{message}}</span><br />
      class对象计算属性绑定:
      <span :class="myClassCompute">{{message}}</span><br />
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          message: "Hello",
          isActive: true,
          isUnderline: false,
        },
        computed: {
          myClassCompute: function () {
            return { active: this.isActive, underline: this.isUnderline };
          },
        },
        methods: {
          changeActive() {
            this.isActive = !this.isActive;
          },
          myClassMthod() {
            return { active: this.isActive, underline: this.isUnderline };
          },
        },
      });
    </script>
  </body>
</html>

# 绑定数组(使用较少)

细节同绑定对象

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <style>
      .active {
        color: red;
      }

      .underline {
        text-decoration: underline;
      }
    </style>
  </head>

  <body>
    <div id="app">
      class数组写死:
      <span :class="['active','underline']">{{message}}</span><br />
      class数组绑定:
      <span :class="[active,underline]">{{message}}</span><br />

      class数组方法绑定:
      <span :class="myClassMthod()">{{message}}</span><br />
      class数组计算属性绑定:
      <span :class="myClassCompute">{{message}}</span><br />
      多个条件 class,可以在数组中包含对象。当 is3 和 is4 都为真时,渲染为三个 class,否则哪个为真渲染哪个
      <span :class="[active, { class3: is3, class4: is4 }]"></span>
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          message: "Hello",
          active: "class1",
          underline: "class2",
          is3: true,
          is4: false,
        },
        computed: {
          myClassCompute: function () {
            return [this.active, this.underline];
          },
        },
        methods: {
          myClassMthod() {
            return [this.active, this.underline];
          },
        },
      });
    </script>
  </body>
</html>

# 绑定内联样式 style—组件化 🔥

常用于组件化开发时改变组建的样式!!!

# 绑定对象(使用很多)

与绑定 Class 不同的是:对象的键不是类名,而是属性名,且属性名称支持 kebab-case 和 camelCase。值为一个变量常量需要使用引号包裹,否则当变量编译时报错。

同样可以封装到 methods 或 computed 中,略

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <style></style>
  </head>

  <body>
    <div id="app">
      <!-- 写死 -->
      <h2 :style="{fontSize: '16px'}">{{message}}</h2>
      <!-- 动态 -->
      <h2 :style="{fontSize: finalSize1}">{{message}}</h2>
      <h2 :style="{fontSize: finalSize2 + 'px', backgroundColor: finalBgc}">
        {{message}}
      </h2>
      <!-- 方法 -->
      <h2 :style="myStyleMethod()">
        {{message}}
      </h2>
      <!-- 计算属性 -->
      <h2 :style="myStyleComputed">
        {{message}}
      </h2>
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          message: "Hello",
          finalSize1: "24px",
          finalSize2: "24",
          finalBgc: "skyblue",
        },
        computed: {
          myStyleComputed: function () {
            return {
              fontSize: this.finalSize2 + "px",
              backgroundColor: this.finalBgc,
            };
          },
        },
        methods: {
          myStyleMethod() {
            return {
              fontSize: this.finalSize2 + "px",
              backgroundColor: this.finalBgc,
            };
          },
        },
      });
    </script>
  </body>
</html>

# 绑定数组(使用较少)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <style></style>
  </head>

  <body>
    <div id="app">
      <h2 :style="[baseStyle1, baseStyle2]">Hello</h2>
      <h2 :style="myBaseStyleMethod()">Hello</h2>
      <h2 :style="myBaseStyleComputed">Hello</h2>
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          // style 中也是键制对,必须用对象
          baseStyle1: { fontSize: "32px" },
          baseStyle2: { background: "skyblue" },
        },
        computed: {
          myBaseStyleComputed: function () {
            return [this.baseStyle1, this.baseStyle2];
          },
        },
        methods: {
          myBaseStyleMethod: function () {
            return [this.baseStyle1, this.baseStyle2];
          },
        },
      });
    </script>
  </body>
</html>

# 内联字符串拼接 🔥

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>

  <body>
    <div id="app">
      <img src="https://cn.vuejs.org/images/logo.png" alt="" />
      <!-- 内联字符串拼接,fileName为变量 -->
      <img :src="'https://cn.vuejs.org/images/' + fileName" />
      <!-- 字符串模板 -->
      <img :src="`https://cn.vuejs.org/images/${fileName}`" />
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          message: "Hello",
          fileName: "logo.png",
        },
      });
    </script>
  </body>
</html>

# 作业1—点击行换色 🔥

注意,尽量不要直接操作 DOM,学习的是 Vue,尽量通过 Vue 来完成。

思考:使用 v-bind 时,如何可以让选中的行变色?需要有个变量存储“选中的行”,常量为 for 循环出的 index,分析这俩间的关系即可得出,当“选中的行” 等于 index 时,激活 class 即可

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <style>
      .active {
        color: red;
      }
    </style>
  </head>

  <body>
    <div id="app">
      <ul>
        <li
          v-for="(item,index) in movies"
          @click="changeColor(index)"
          :class="{active: currentIndex === index}"
        >
          {{index}}-{{item}}
        </li>
      </ul>
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          movies: ["名侦探柯南", "怪盗基德", "犬夜叉", "龙珠"],
          currentIndex: 0, // 当前选中的行数
        },
        methods: {
          changeColor(index) {
            console.log(index);
            this.currentIndex = index;
          },
        },
      });
    </script>
  </body>
</html>